
-- 在加 行级锁 前 会加相应的 意向锁 比如意向共享锁 或者 意向独占锁

-- 行级锁的类型主要有三类:
-- ·Record Lock，记录锁，也就是仅仅把一条记录锁上;  更新一行数据时就会上  记录锁
-- ·Gap Lock，间隙锁，锁定一个范围，但是不包含记录本身  只存在于 可重复读隔离级别  X 和 S 是一样的 都是共享的 目的是解决 幻读
--     MVVC + 间隙锁  解决幻读
-- ·Next-Key Lock:Record Lock+ Gap Lock的组合，锁定一个范围，并且锁定记录本身。


# 建表语句
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` int NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_age` (`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `user` VALUES (1, 'A', 10);
INSERT INTO `user` VALUES (2, 'B', 14);
INSERT INTO `user` VALUES (3, 'C', 17);
INSERT INTO `user` VALUES (4, 'D', 29);
INSERT INTO `user` VALUES (5, 'E', 35);
INSERT INTO `user` VALUES (15, 'F', 40);


## 查看隔离级别
SELECT @@global.transaction_isolation;

SELECT @@transaction_isolation;
# REPEATABLE-READ


-- -----------------------------------------------------主键索引 等值查询（where id = xxx）


# 锁定读 记录存在 主键索引加记录锁  表加意向独占锁  防止幻读：
begin;
SELECT * FROM user WHERE id = 1 FOR UPDATE;

commit ;
# 查询 当前的加锁情况
select * from performance_schema.data_locks;




# 锁定读 记录不存在 主键索引加间隙锁  表加意向独占锁 ：
begin;
SELECT * FROM user WHERE id = 10 FOR UPDATE;

commit ;
# 查询 当前的加锁情况
select * from performance_schema.data_locks;


# 锁定读 记录不存在且超过了主键最大值  主键索引加临键锁  表加意向独占锁 ：
begin;
SELECT * FROM user WHERE id = 100 FOR UPDATE;

commit ;
# 查询 当前的加锁情况
select * from performance_schema.data_locks;



-- -----------------------------------------------------非唯一索引 二级索引 等值查询（where age = xxx）

# 锁定读  记录存在   age 加临键锁 以及 间隙锁  主键索引加记录锁  表加意向独占锁：
begin;
SELECT * FROM user WHERE age = 14 FOR UPDATE;

commit ;

select * from performance_schema.data_locks;

# 锁定读  记录不存在 且不大于age 最大值  非唯一索引 age索引 加间隙锁  表加意向独占锁：
begin;
SELECT * FROM user WHERE age = 25 FOR UPDATE;

commit ;

select * from performance_schema.data_locks;



# 锁定读  记录不存在 且大于age 最大值  非唯一索引 age索引 加临键锁  表加意向独占锁：
begin;
SELECT * FROM user WHERE age = 99 FOR UPDATE;

commit ;

select * from performance_schema.data_locks;


## 修改索引结构 把 age 索引 改为 唯一索引
ALTER TABLE user DROP INDEX index_age, ADD UNIQUE INDEX index_age (age);

## 修改索引结构 把 age 索引 改为 非唯一索引
ALTER TABLE user DROP INDEX index_age, ADD INDEX index_age (age);